﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;

namespace DBUtil
{
    /// <summary>
    /// 当前数据库行为规则
    /// </summary>
    public class DBSetting
    {
        private DBSetting() { }

        /// <summary>
        /// 默认的配置
        /// </summary>
        internal static DBSetting Default = new DBSetting();

        #region Id和流水号生成
        /// <summary>
        /// 基于数据库的Id生成控制的存储过程名称,默认为"__proc_generateid"
        /// </summary>
        public string DBCacheGeneratorIdProcedureName { get; internal set; } = "__proc_generateid";

        /// <summary>
        /// 基于数据库的Id生成控制的表名称,默认为"__generator_id"
        /// </summary>
        public string DBCacheGeneratorIdTableName { get; internal set; } = "__generator_id";

        /// <summary>
        /// 基于数据库的Id生成控制的日志表名称,默认为"__generator_err_log"
        /// </summary>
        public string DBCacheGeneratorLogTableName { get; internal set; } = "__generator_err_log";

        /// <summary>
        /// 基于数据库的流水号生成控制的存储过程名称,默认为"__proc_generatesno"
        /// </summary>
        public string DBCacheGeneratorSNOProcedureName { get; internal set; } = "__proc_generatesno";

        /// <summary>
        /// 基于数据库的流水号生成控制的表名称,默认为"__generator_sno"
        /// </summary>
        public string DBCacheGeneratorSNOTableName { get; internal set; } = "__generator_sno";
        #endregion

        #region 分布式锁
        /// <summary>
        /// 基于数据库的分布式锁使用的表名称,默认为"__db_lock"
        /// </summary>
        internal string DBLockTableName { get; set; } = "__db_lock";
        #endregion

        #region 执行sql配置
        /// <summary>
        /// 执行sql命令超时时间
        /// </summary>
        internal int? CommandTimeout { get; set; } = null;
        #endregion

        internal Dictionary<string, object> ExtendSettings = new Dictionary<string, object>();

        /// <summary>
        /// 克隆一个配置对象
        /// </summary>
        /// <returns></returns>
        public DBSetting Clone()
        {
            var setting = new DBSetting()
            {
                DBCacheGeneratorIdProcedureName = DBCacheGeneratorIdProcedureName,
                DBCacheGeneratorIdTableName = DBCacheGeneratorIdTableName,
                DBCacheGeneratorLogTableName = DBCacheGeneratorLogTableName,
                DBCacheGeneratorSNOProcedureName = DBCacheGeneratorSNOProcedureName,
                DBCacheGeneratorSNOTableName = DBCacheGeneratorSNOTableName,
                DBLockTableName = DBLockTableName,
                //UseParameter = UseParameter,
                CommandTimeout = CommandTimeout
            };
            foreach (var item in ExtendSettings)
            {
                setting.ExtendSettings.Add(item.Key, item.Value);
            }
            return setting;
        }

        public T GetExtend<T>(string name)
        {
            if (ExtendSettings.TryGetValue(name, out var setting))
            {
                return (T)setting;
            }
            else
            {
                return default(T);
            }
        }
    }

    public class DBSettingBuilder
    {
        internal DBSetting Setting { get; set; }
        public static DBSettingBuilder CreateBuilder(DBSetting setting = null)
        {
            return new DBSettingBuilder()
            {
                Setting = setting ?? DBSetting.Default.Clone()
            };
        }

        public DBSetting Build() => Setting;

        public DBSettingBuilder UseDBCacheGeneratorIdProcedureName(string name)
        {
            Setting.DBCacheGeneratorIdProcedureName = name;
            return this;
        }

        public DBSettingBuilder UseDBCacheGeneratorIdTableName(string name)
        {
            Setting.DBCacheGeneratorIdTableName = name;
            return this;
        }

        public DBSettingBuilder UseDBCacheGeneratorLogTableName(string name)
        {
            Setting.DBCacheGeneratorLogTableName = name;
            return this;
        }

        public DBSettingBuilder UseDBCacheGeneratorSNOProcedureName(string name)
        {
            Setting.DBCacheGeneratorSNOProcedureName = name;
            return this;
        }

        public DBSettingBuilder UseDBCacheGeneratorSNOTableName(string name)
        {
            Setting.DBCacheGeneratorSNOTableName = name;
            return this;
        }

        public DBSettingBuilder UseDBLockTableName(string name)
        {
            Setting.DBLockTableName = name;
            return this;
        }

        public DBSettingBuilder UseCommandTimeout(int millisecond)
        {
            Setting.CommandTimeout = millisecond;
            return this;
        }

        public DBSettingBuilder UseExtendSetting(string name, object instant)
        {
            Setting.ExtendSettings.Add(name, instant);
            return this;
        }
    }
}
